package com.framework.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.framework.common.exception.RRException;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import com.sun.org.apache.xalan.internal.xsltc.dom.SimpleResultTreeImpl;
import com.tencentcloudapi.cmq.v20190304.models.CreateQueueResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Modifier;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;

public class QuickHelper {

    protected static Logger logger = LoggerFactory.getLogger(QuickHelper.class);

    public static String object2json(Object obj) {
        return JSON.toJSONString(obj, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteDateUseDateFormat);
    }

    /**
     * JSON转Object对象
     */
    public static <T> T json2object(String json, Class<T> cls) {
        T result = null;
        try {
            result = JSON.parseObject(json, cls);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    public static <V> Map<String,V> createMap(String key,V value) {
        Map<String, V> map = new HashMap<>();
        map.put(key, value);
        return map;
    }

    public static <V> Map<String,V> createMultiMap(KeyValue... params) {
        Map<String, V> map = new HashMap<>();
        for (Object param : params) {
            KeyValue kv = (KeyValue) param;
            if (param != null) {
                map.put(kv.getKey().toString(), (V) kv.getValue());
            }
        }
        return map;
    }


    /**
     * 获取指定字符串的指定类型
     *
     * @param value        原始值
     * @param defaultValue 默认值
     * @param <T>
     * @return
     */
    public static <T> T checkStringOrDefaultValue(String value, T defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        Class<?> clazz = defaultValue.getClass();

        if (value.equals("")) {
            return defaultValue;
        }


        T ret = defaultValue;
        try {
            switch (clazz.getSimpleName()) {
                case "String":
                    ret = (T) String.valueOf(value);
                    break;

                case "Integer":
                    ret = (T) Integer.valueOf(value);
                    break;
                default:

                    break;
            }
        } catch (Exception e) {
            logger.warn(String.format("转换错误：%s", e.getMessage()));
        }
        return ret;
    }

    public static int get_random_code(int start, int end) {

        int num = (int) (Math.random() * (end - start + 1) + start);
        return num;
    }

    /**
     * 获取现在时间的时间戳：以秒数为单位的
     *
     * @return
     */
    public static Integer getNowTimeStampSeconds() {
        return DateUtils.getSecondTimestamp(new Date());
    }


    /**
     * 生成一个要上传到云存储的文件路径
     *
     * @param suffix 文件扩展名
     * @param dir    要存到到云存储区的父路径
     * @return
     */
    public static String createCloudStorageFileName(String suffix, String dir) {
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        String path = dir + '/' + DateUtils.format(new Date(), "yyyyMMdd") + "/" + uuid + suffix;
        return path;
    }


    /**
     * 根据属性名获取属性值
     */
    public static Object getClassFieldValueByName(String fieldName, Object o) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter, new Class[]{});
            Object value = method.invoke(o, new Object[]{});
            return value;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取属性名数组
     */
    public static String[] getClassFiledNameArray(Object o) {
        Field[] fields = o.getClass().getDeclaredFields();
        String[] fieldNames = new String[fields.length];
        for (int i = 0; i < fields.length; i++) {
            System.out.println(fields[i].getType());
            fieldNames[i] = fields[i].getName();
        }
        return fieldNames;
    }

    /**
     * 获取属性名list
     */
    public static List<String> getClassFiledNameArray(Class clazz) {
        Field[] fields = clazz.getDeclaredFields();
        List<String> fieldNames = new ArrayList<>(fields.length);
        for (int i = 0; i < fields.length; i++) {
            fieldNames.add(fields[i].getName());
        }
        return fieldNames;
    }

    /**
     * 获取属性类型(type)，属性名(name)，属性值(value)的map组成的list
     */
    public static <T> Map<String, T> getClassFiledsMap(Object o) {
        Field[] fields = o.getClass().getDeclaredFields();
        String[] fieldNames = new String[fields.length];
        Map infoMap = new HashMap();
        for (int i = 0; i < fields.length; i++) {
            Map subMap = new HashMap();
            subMap.put("type", fields[i].getType().toString());
            subMap.put("name", fields[i].getName());
            subMap.put("value", getClassFieldValueByName(fields[i].getName(), o));
            infoMap.put(fields[i].getName(), subMap);
        }
        return infoMap;
    }

    /**
     * 将某个实体类(不包括静态字段)转化为一个 Map ,　结构如下
     * map[fieldName] = fieldValue
     * @param o
     * @param <T>
     * @return
     */
    public static <T> Map<String, T> getClassFiledsKeyValueMap(Object o) {
        Field[] fields = o.getClass().getDeclaredFields();
        Map kvMap = new HashMap();
        for (int i = 0; i < fields.length; i++) {
            //如果是静态变量，则不加入到 map
            if(Modifier.isStatic(fields[i].getModifiers())){
                break;
            }
            String name = fields[i].getName();
            Object value = getClassFieldValueByName(fields[i].getName(), o);
            kvMap.put(name, value);
        }
        return kvMap;
    }

    /**
     * 获取对象的所有属性值，返回一个对象数组
     */
    public static Object[] getClassFiledValues(Object o) {
        String[] fieldNames = getClassFiledNameArray(o);
        Object[] value = new Object[fieldNames.length];
        for (int i = 0; i < fieldNames.length; i++) {
            value[i] = getClassFieldValueByName(fieldNames[i], o);
        }
        return value;
    }

    /**
     * base64 解码
     *
     * @param str
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String base64decode(String str) throws UnsupportedEncodingException {
        return new String(Base64.getDecoder().decode(str), "UTF-8");
    }

    public static String md5(String buffer) {
        String string = null;
        char hexDigist[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        MessageDigest md;
        try {
            md = MessageDigest.getInstance("MD5");
            md.update(buffer.getBytes());
            byte[] datas = md.digest(); //16个字节的长整数

            char[] str = new char[2 * 16];
            int k = 0;

            for (int i = 0; i < 16; i++) {
                byte b = datas[i];
                str[k++] = hexDigist[b >>> 4 & 0xf];//高4位
                str[k++] = hexDigist[b & 0xf];//低4位
            }
            string = new String(str);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return string;
    }

    /**
     * 从当前的 Spring 环境变量中获取一个参数，并将其转化为一个类
     * @param name 参数名
     * @param clazz 反序列化的目标类
     * @param <T>
     * @return
     */
    public static <T> T getConfigValue(String name,Class<T> clazz) {
        Environment env = SpringContextUtils.applicationContext.getEnvironment();
        String str = env.getProperty(name);

        if (str == null) {
            throw new RRException(String.format("当前获取的系统配置为 %s = null .", name));
        }
        try{
            T t = QuickHelper.json2object(str, clazz);
            return t;
        }
        catch (Exception e){
            e.printStackTrace();
            throw e;
        }
    }

    public static Integer getConfigIntegerValue(String name){
        return getConfigValue(name,Integer.class);
    }

    public static JSONArray getConfigJSONArray(String name) {
        return getConfigValue(name, JSONArray.class);
    }

    public static JSONObject getConfigJSONObject(String name) {
        return getConfigValue(name, JSONObject.class);
    }

    /**
     * 直接获取String类型的配置
     * @param name
     * @return
     */
    public static String getConfigString(String name) {
        Environment env = SpringContextUtils.applicationContext.getEnvironment();
        String str = env.getProperty(name);

        if (str == null) {
            throw new RRException(String.format("名字为 %s 参数值为 null .", str));
        }
        return str;
    }


    /**
     * 将 Map 的 value　转化为 字符串数组
     * @param map
     * @param <T>
     * @return
     */
    public static <T> String[] getMapValueStringArray(Map<String,T> map) {
        String[] array = new String[map.size()];
        Integer index=0;
        for (String name : map.keySet()) {
            T t = map.get(name);
            array[index] = t == null ? "" : t.toString();
            index++;
        }
        return array;
    }


}
